﻿using System;
using System.IO;
using System.Net;
using System.Text;

namespace UselessExplorer.Controller
{
    public class FTPClient
    {
        #region Property
        private const int DefaultPort = 21;
        private const int DefaultTimeoutPeriod = 10000;

        private string m_FtpServer;

        public string FtpServer
        {
            get { return m_FtpServer; }
            set { m_FtpServer = value; }
        }

        private string m_UserName;

        public string UserName
        {
            get { return m_UserName; }
            set { m_UserName = value; }
        }

        private string m_Password;

        public string Password
        {
            get { return m_Password; }
            set { m_Password = value; }
        }

        private int m_port;

        public int Port
        {
            get { return m_port; }
            set { m_port = value; }
        }
        #endregion

        #region Constructor
        public FTPClient()
        {
            if (m_FtpServer == null || m_UserName == null || m_Password == null)
                throw new Exception("Params not defined");
        }

        public FTPClient(string server, string user, string pass)
        {
            m_FtpServer = server;
            m_UserName = user;
            m_Password = pass;
            m_port = DefaultPort;
        }

        public FTPClient(string server, string user, string pass, int port)
        {
            m_FtpServer = server;
            m_UserName = user;
            m_Password = pass;
            m_port = port;
        }

        #endregion

        private bool Connect(out FtpWebRequest reqFTP)
        {
            try
            {
                reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + FtpServer + "/"));
                reqFTP.Timeout = DefaultTimeoutPeriod;
                return true;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        
        public string[] GetFileList()
        {
            string[] downloadFiles;
            StringBuilder result = new StringBuilder();
            FtpWebRequest reqFTP;

            try
            {
                Connect(out reqFTP);
                reqFTP.UseBinary = true;
                reqFTP.KeepAlive = false;
                reqFTP.Credentials = new NetworkCredential(UserName, Password);
                reqFTP.Method = WebRequestMethods.Ftp.ListDirectory;
                
                FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
                StreamReader reader = new StreamReader(response.GetResponseStream());

                //PrintStatusMessage(response.WelcomeMessage);
               // PrintStatusMessage(response.StatusDescription);

                string line = reader.ReadLine();

                while (line != null)
                {
                    result.Append(line);
                    result.Append("\n");
                    line = reader.ReadLine();
                }

                // to remove the trailing '\n'
                result.Remove(result.ToString().LastIndexOf('\n'), 1);
                reader.Close();
                response.Close();
               // btnFtpDisconnect.Enabled = true;
                return result.ToString().Split('\n');
            }
            catch (Exception ex)
            {
                Logger.Instance.WriteLogs(Logger.LogsCategory.Exception, ex);
                downloadFiles = null;
                //enableInputs();
                return downloadFiles;
            }
        }


        private void Download(string filePath, string fileName)
        {
            string ftpServerIP = m_FtpServer;
            FtpWebRequest reqFTP;

            try
            {
                Connect(out reqFTP);

                FileStream outputStream = new FileStream(filePath + "\\" + fileName, FileMode.Create);
                reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + ftpServerIP + "/" + fileName));
                reqFTP.Method = WebRequestMethods.Ftp.DownloadFile;
                reqFTP.UseBinary = true;
                reqFTP.Credentials = new NetworkCredential(UserName, Password);
                FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
                Stream ftpStream = response.GetResponseStream();
                long cl = response.ContentLength;
                int bufferSize = 2048;
                int readCount;
                byte[] buffer = new byte[bufferSize];
                readCount = ftpStream.Read(buffer, 0, bufferSize);
                while (readCount > 0)
                {
                    outputStream.Write(buffer, 0, readCount);
                    readCount = ftpStream.Read(buffer, 0, bufferSize);
                }

                ftpStream.Close();
                outputStream.Close();
                response.Close();
            }
            catch (Exception ex)
            {
               Logger.Instance.WriteLogs(Logger.LogsCategory.Exception, ex);
            }
        }

        private void Upload(string filename)
        {
            FileInfo fileInf = new FileInfo(filename);
            string uri = "ftp://" + UserName + "/" + fileInf.Name;
            FtpWebRequest reqFTP;
            // Create FtpWebRequest object from the Uri provided
            reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + FtpServer + "/" + fileInf.Name));
            // Provide the WebPermission Credintials
            reqFTP.Credentials = new NetworkCredential(UserName, Password);
            // By default KeepAlive is true, where the control connection is not closed
            // after a command is executed.
            reqFTP.KeepAlive = false;
            // Specify the command to be executed.
            reqFTP.Method = WebRequestMethods.Ftp.UploadFile;
            // Specify the data transfer type.
            reqFTP.UseBinary = true;
            // Notify the server about the size of the uploaded file
            reqFTP.ContentLength = fileInf.Length;
            // The buffer size is set to 2kb
            int buffLength = 2048;
            byte[] buff = new byte[buffLength];
            int contentLen;
            // Opens a file stream (System.IO.FileStream) to read the file to be uploaded
            FileStream fs = fileInf.OpenRead();
            try
            {
                // Stream to which the file to be upload is written
                Stream strm = reqFTP.GetRequestStream();
                // Read from the file stream 2kb at a time
                contentLen = fs.Read(buff, 0, buffLength);
                // Till Stream content ends
                while (contentLen != 0)
                {
                    // Write Content from the file stream to the FTP Upload Stream
                    strm.Write(buff, 0, contentLen);
                    contentLen = fs.Read(buff, 0, buffLength);
                }

                // Close the file stream and the Request Stream
                strm.Close();
                fs.Close();
            }
            catch (Exception ex)
            {
                Logger.Instance.WriteLogs(Logger.LogsCategory.Exception, ex);
            }
        }

        public long GetFileSize(string file)
        {
            try
            {
                FtpWebRequest req = (FtpWebRequest)WebRequest.Create("ftp://" + FtpServer + "/" + file);
                req.Proxy = null;
                req.Credentials = new NetworkCredential(UserName, Password);

                req.Method = WebRequestMethods.Ftp.GetFileSize;

                using (WebResponse resp = req.GetResponse())
                    return resp.ContentLength;
            }
            catch (Exception ex)
            {
                FileNotFoundException fe = new FileNotFoundException();
                if (!fe.Equals(ex))
                {
                    Logger.Instance.WriteLogs(Logger.LogsCategory.Exception, ex);
                    return 0;
                }
                else
                {
                    return 0;
                }
            }

        }

        public string GetTimeStamp(string file)
        {
            try
            {
                FtpWebRequest req = (FtpWebRequest)WebRequest.Create("ftp://" + FtpServer + "/" + file);
                req.Proxy = null;
                req.Credentials = new NetworkCredential(UserName, Password);

                req.Method = WebRequestMethods.Ftp.GetDateTimestamp;

                using (FtpWebResponse resp = (FtpWebResponse)req.GetResponse())
                    return resp.LastModified.ToShortDateString();
            }
            catch (Exception ex)
            {
                Logger.Instance.WriteLogs(Logger.LogsCategory.Exception, ex);
                return null;
            }
        }
    }

}
